package com.duoec.dw.lineage.service.analyser.field;

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLCastExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
import com.duoec.dw.lineage.core.utils.AnalyserUtils;
import com.duoec.dw.lineage.dto.MultiTableLineageDto;
import com.duoec.dw.lineage.dto.TableFieldDependencyDto;
import com.duoec.dw.lineage.dto.TableFieldLineageDto;
import com.duoec.dw.lineage.dto.TableLineageDto;
import com.google.common.collect.Sets;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @author xuwenzhen
 */
@Service
public class DefaultFieldAnalyser extends BaseFieldAnalyser<SQLExpr> {

    private static final Set<String> HIVE_FUN_SET = Sets.newHashSet(
            "CURRENT_TIMESTAMP"
    );

    /**
     * 当前类处理的类型
     *
     * @return SQLExpr的子类
     */
    @Override
    public Class<SQLExpr> getSelectFieldType() {
        return SQLExpr.class;
    }

    /**
     * 解析 select
     *
     * @param selectFieldExpr   需要解析的select field
     * @param tableLineage      当前表的血缘关系信息
     * @param fromTableLineages 当前查询依赖字段的多表血缘关系
     */
    @Override
    public LinkedHashSet<TableFieldLineageDto> analyse(SQLExpr selectFieldExpr, TableLineageDto tableLineage, MultiTableLineageDto fromTableLineages) {
        LinkedHashSet<TableFieldLineageDto> fields = tableLineage.getFields();

        String fieldName;
        if (selectFieldExpr instanceof SQLPropertyExpr) {
            fieldName = ((SQLPropertyExpr) selectFieldExpr).getName();
        } else if (selectFieldExpr instanceof SQLCastExpr) {
            //这个类型得这样取，否则会取到 SQLCastExpr@xxxx这样的字符串
            fieldName = selectFieldExpr.getParent().toString();
        } else {
            fieldName = selectFieldExpr.toString();
        }
        fieldName = AnalyserUtils.formatFieldName(fieldName);
        TableFieldLineageDto fieldLineageDto = new TableFieldLineageDto();
        fieldLineageDto.setIndex(fields.size());
        if (HIVE_FUN_SET.contains(fieldName.toUpperCase()) || selectFieldExpr instanceof SQLValuableExpr) {
            //内置函数
            fieldLineageDto.setValuable(true);
        } else {
            fieldLineageDto.setColName(fieldName);
            LinkedHashSet<TableFieldDependencyDto> dependencies = hiveAnalyser.analyseExpr(fromTableLineages, selectFieldExpr);
            if (CollectionUtils.isEmpty(dependencies)) {
                fieldLineageDto.setValuable(true);
            } else {
                fieldLineageDto.setDependencies(dependencies);
            }
        }

        LinkedHashSet<TableFieldLineageDto> fieldLineages = new LinkedHashSet<>();
        fieldLineages.add(fieldLineageDto);
        return fieldLineages;
    }
}
